package com.sloan.community.controller;

import com.sloan.community.common.Login;
import com.sloan.community.common.command.ArticleCommand;
import com.sloan.community.common.query.ArticleSearchQuery;
import com.sloan.community.common.res.Result;
import com.sloan.community.common.vo.ArticleVO;
import com.sloan.community.po.User;
import com.sloan.community.service.ArticleService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.WebSession;
import reactor.core.publisher.Mono;

import static com.sloan.community.common.Constant.SESSION_USER;

@Slf4j
@Controller
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
@RequestMapping("article")
public class ArticleController {

    private final ArticleService articleService;

    @Login
    @GetMapping("add-article")
    public Mono<String> article(Model model) {
        return articleService.detail(null, null)
                .map(item -> {
                    model.addAttribute("detail", item);
                    return "addArticle";
                });
    }

    @Login
    @GetMapping(value = {"search", "list"})
    public Mono<String> search(ArticleSearchQuery param,
                               Model model, WebSession session) {
        User user = session.getAttribute(SESSION_USER);
        if (user == null) {
            return Mono.just("login");
        }
        model.addAttribute("keyword", param.getKeyword());
        return articleService.searchCondition(param, user.getId())
                .doOnNext(item -> {
                    model.addAttribute("page", item);
                })
                .map(item -> "articleList");
    }

    @Login
    @GetMapping("{id}")
    public Mono<String> detail(@PathVariable(value = "id")
                               @Min(value = 1L, message = "参数错误") Long id,
                               User user, Model model) {
        return articleService.detail(id, user.getId())
                .map(item -> {
                    model.addAttribute("detail", item);
                    return "addArticle";
                });
    }

    @Login
    @ResponseBody
    @PostMapping
    public Mono<Result<ArticleVO>> add(@RequestBody @Valid ArticleCommand article,
                                       User user) {
        return articleService.add(article, user)
                .map(Result::success);
    }

    @Login
    @ResponseBody
    @PutMapping("{id}")
    public Mono<Result<Boolean>> edit(@PathVariable("id") Long id,
                                      @RequestBody ArticleCommand article,
                                      User user) {
        return articleService.update(id, article, user.getId())
                .map(item -> Result.success(Boolean.TRUE));
    }

    @Login
    @ResponseBody
    @DeleteMapping("{id}")
    public Mono<Result<Boolean>> delete(@PathVariable("id") Long id, User user) {
        return articleService.delete(id, user.getId())
                .then(Mono.fromCallable(() -> Result.success(Boolean.TRUE)));
    }

    @Login
    @ResponseBody
    @PutMapping("status/comment/{id}")
    public Mono<Result<Boolean>> commentSwitch(@PathVariable("id") Long id,User user) {
        return articleService.commentSwitch(id, user.getId())
                .then(Mono.fromCallable(() -> Result.success(Boolean.TRUE)));
    }

    @Login
    @ResponseBody
    @PutMapping("status/appreciation/{id}")
    public Mono<Result<Boolean>> appreciationSwitch(@PathVariable("id") Long id, User user) {
        return articleService.appreciationSwitch(id, user.getId())
                .then(Mono.fromSupplier(() -> Result.success(Boolean.TRUE)));
    }

    @Login
    @ResponseBody
    @PutMapping("status/recommend/{id}")
    public Mono<Result<Boolean>> recommendSwitch(@PathVariable("id") Long id,User user) {
        return articleService.recommendSwitch(id, user.getId())
                .then(Mono.just(Result.success(Boolean.TRUE)));
    }

    @Login
    @ResponseBody
    @PutMapping("status/share/{id}")
    public Mono<Result<Boolean>> shareableSwitch(@PathVariable("id") Long id, User user) {
        return articleService.shareSwitch(id, user.getId())
                .then(Mono.fromCallable(() -> Result.success(Boolean.TRUE)));
    }


}
